/* eslint-disable no-unused-vars */
import AppError from "../errors";

export const CODE_PROCEED_FAILURE = 999999;
export const CODE_PROCEED_OK = 200;
export const CODE_PROCEED_ACCEPTED = 202;
export const CODE_PROCEED_NO_CONTENT = 204;
export const CODE_PROCEED_RESET_CONTENT = 205;
export const CODE_PROCEED_PARTIAL_CONTENT = 206;
export const CODE_REDIRECT_MOVED_PERMANENTLY = 301;
export const CODE_REDIRECT_FOUND = 302;
export const CODE_REDIRECT_SEE_OTHER = 303;
export const CODE_REDIRECT_NOT_MODIFIED = 304;
export const CODE_CLIENT_BADREQUEST = 400;
export const CODE_CLIENT_UNAUTHORIZED = 401;
export const CODE_CLIENT_FORBIDDEN = 403;
export const CODE_CLIENT_UNPROCESSABLE_ENTITY = 422;
export const CODE_CLIENT_NOTFOUND = 404;
export const CODE_CLIENT_METHOD_NOT_ALLOWED = 405;
export const CODE_CLIENT_CONFLICT = 409;
export const CODE_CLIENT_PRECONDITION_REQUIRED = 428;
export const CODE_CLIENT_UNSUPPORTED_MEDIA_TYPE = 415;
export const CODE_SERVER_INTERNALERROR = 500;
export const CODE_SERVER_NOTIMPLEMENTED = 501;
export const CODE_SERVER_BAD_GATEWAY = 502;
export const CODE_SERVER_UNAVAILABLE = 503;
export const CODE_SERVER_TIMEOUT = 504;
export const CODE_SERVER_VERSIONNOTSUPPORTED = 505;

/** 全局成功标识代码 */
export const API_STATUS_OK = 0;
/** 全局未知错误标识代码 */
export const API_STATUS_ERROR = 1;
// 信息
export const API_STATUS_INFO = 2;
// 警告
export const API_STATUS_WARN = 3;
// 确认
export const API_STATUS_CONF = 4;

/** 全局成功标识代码 */
export const API_STATUS_LABEL_OK = "success";
/** 全局未知错误标识代码 */
export const API_STATUS_LABEL_ERROR = "error";
// 信息
export const API_STATUS_LABEL_INFO = "info";
// 警告
export const API_STATUS_LABEL_WARN = "warning";
// 确认
export const API_STATUS_LABEL_CONF = "confirm";
export const getStatusLabel = status => {
  switch (status) {
    case API_STATUS_ERROR:
      return API_STATUS_LABEL_ERROR;
    case API_STATUS_INFO:
      return API_STATUS_LABEL_INFO;
    case API_STATUS_WARN:
      return API_STATUS_LABEL_WARN;
    case API_STATUS_CONF:
      return API_STATUS_LABEL_CONF;
    case API_STATUS_OK:
    default:
      return API_STATUS_LABEL_OK;
  }
};
export const build = (...values) => {
  return ApiResult.build(...values);
};
export const onlyInfo = result => {
  return ApiResult.onlyInfo(result);
};
export const isOk = result => {
  return ApiResult.isOk(result);
};
export const notError = result => {
  return ApiResult.notError(result);
};
export const buildResult = values => {
  return ApiResult.build(values);
};
export const ApiResult = class ApiResult {
  constructor(...values) {
    this.statusCode = 0;
    this.status = 0;
    this.code = 0;
    this.message = "";
    this.data = {};
    this.assign(...values);
  }

  notError() {
    return this.status !== API_STATUS_ERROR;
  }

  isOk() {
    return this.status === API_STATUS_OK;
  }

  onlyInfo() {
    return this.status !== API_STATUS_OK && this.status !== API_STATUS_ERROR;
  }

  static notError(result) {
    if (result instanceof ApiResult) {
      return result.notError();
    } else if ("object" === typeof result && null !== result) {
      if ("undefined" !== result.status) {
        return result.status !== API_STATUS_ERROR;
      } else if ("undefined" !== result["status"]) {
        return result["status"] !== API_STATUS_ERROR;
      }
    }
    return false;
  }

  static isOk(result) {
    if (result instanceof ApiResult) {
      return result.notError();
    } else if ("object" === typeof result && null !== result) {
      if ("undefined" !== result.status) {
        return result.status === API_STATUS_OK;
      } else if ("undefined" !== result["status"]) {
        return result["status"] === API_STATUS_OK;
      }
    }
    return false;
  }

  static onlyInfo(result) {
    if (result instanceof ApiResult) {
      return result.notError();
    } else if ("object" === typeof result && null !== result) {
      if ("undefined" !== result.status) {
        return (
          result.status !== API_STATUS_OK && result.status !== API_STATUS_ERROR
        );
      } else if ("undefined" !== result["status"]) {
        return (
          result["status"] !== API_STATUS_OK &&
          result["status"] !== API_STATUS_ERROR
        );
      }
    }
    return false;
  }

  static build(...values) {
    return new ApiResult(...values);
  }

  static buildOk(...datas) {
    return ApiResult.build()
      .setStatus(API_STATUS_OK)
      .setCode(CODE_PROCEED_OK)
      .setMessage("OK")
      .setStatusCode(CODE_PROCEED_OK)
      .setData(...datas);
  }

  static buildError(...datas) {
    return ApiResult.build()
      .setStatus(API_STATUS_ERROR)
      .setCode(CODE_CLIENT_BADREQUEST)
      .setMessage("Error")
      .setStatusCode(CODE_CLIENT_BADREQUEST)
      .setData(...datas);
  }

  static buildInfo(...datas) {
    return (
      ApiResult.build()
        .setStatus(API_STATUS_INFO)
        .setCode(CODE_PROCEED_ACCEPTED)
        .setMessage("Info")
        // .setStatusCode(CODE_PROCEED_ACCEPTED)
        .setData(...datas)
    );
  }

  static buildWarn(...datas) {
    return (
      ApiResult.build()
        .setStatus(API_STATUS_WARN)
        .setCode(CODE_REDIRECT_SEE_OTHER)
        .setMessage("Warning")
        // .setStatusCode(CODE_REDIRECT_SEE_OTHER)
        .setData(...datas)
    );
  }

  static buildConf(...datas) {
    return (
      ApiResult.build()
        .setStatus(API_STATUS_CONF)
        .setCode(CODE_CLIENT_PRECONDITION_REQUIRED)
        .setMessage("Confirm")
        // .setStatusCode(CODE_CLIENT_PRECONDITION_REQUIRED)
        .setData(...datas)
    );
  }

  getStatusCode() {
    return this.statusCode;
  }

  setStatusCode(value) {
    this.statusCode = value;
    return this;
  }

  getStatus() {
    return this.status;
  }

  setStatus(value) {
    this.status = value;
    return this;
  }

  getCode() {
    return this.code;
  }

  setCode(value) {
    this.code = value;
    return this;
  }

  getMessage() {
    return this.message;
  }

  setMessage(...values) {
    this.message = values.join(" ");
    return this;
  }

  getData() {
    return this.data;
  }

  setData(...values) {
    if (values.length > 0) {
      if (values.length > 1) {
        this.data = values;
      } else {
        [this.data] = values;
      }
    }
    return this;
  }

  stripData() {
    this.data = null;
    return this;
  }

  assign(...values) {
    if (values.length > 0) {
      if (values.length > 1) {
        this.data = values;
      } else {
        const results = values[0];
        const normalizedValues =
          "object" === typeof results && null !== results ? results : {};
        Object.keys(normalizedValues).forEach(key => {
          this[key] = normalizedValues[key];
        });
        if (results instanceof Error) {
          this.setStatus(API_STATUS_ERROR);
          if (results instanceof AppError) {
            this.setCode(results.getCode())
              .setMessage(results.getMessage())
              .setData(results.getData());
          }
        }
      }
    }

    return this;
  }

  getStatusLabel(status) {
    if (
      status === null ||
      status === undefined ||
      status === false ||
      status === ""
    ) {
      status = this.status;
    }
    return getStatusLabel(status);
  }

  toString() {
    return this.toJSON();
  }

  /**
   * Get a plain object representation of the struct.
   *
   * @return {Object}
   */
  toObject() {
    return Object.keys(this).reduce((values, key) => {
      values[key] = this[key];
      return values;
    }, {});
  }

  /**
   * Get a JSON string representation of the struct.
   *
   * @return {string}
   */
  toJSON(replacer, space) {
    return JSON.stringify(this.toObject(), replacer, space);
  }
};

// console.log("aaa");
// let m1 = ApiResult.build()
//   .setStatus(API_STATUS_ERROR)
//   // .setCode(200)
//   .setMessage("OK")
//   .toObject();
// let m2 = new ApiResult().setCode(400).setMessage("BAD REQuest");
// // .toObject();
// console.log("m1", m1);
// // console.log("m1dat", m1dat);
// // console.log("m1", m1);
// console.log("m2", m2);
// console.log("m2 status", m2.getStatus());
// console.log("m2 statusLabel", m2.getStatusLabel());
// console.log("m2 statusLabel set ", m2.getStatusLabel(API_STATUS_WARN));
export default ApiResult;
